#ifndef __IMCRYPTO_H__
#define __IMCRYPTO_H__

class IMCrypto
{
public:
	typedef enum
	{
		CT_NULL,
		CT_DES,
		CT_DES3,
		CT_AES128,
		CT_AES192,
		CT_AES256,
	} CRYPTO_TYPE;

	typedef enum
	{
		PT_NULL,
		PT_ECB,
		PT_CFB64,
		PT_CFB1,
		PT_CFB8,
		PT_CFB128,
		PT_OFB,
		PT_CBC,
	} PADDING_TYPE;

public:
	static IMCrypto* s_createEncrypt(CRYPTO_TYPE ct, PADDING_TYPE pt, const unsigned char* key, const unsigned char* iv, size_t padding_size = (size_t)-1);
	static IMCrypto* s_createDecrypt(CRYPTO_TYPE ct, PADDING_TYPE pt, const unsigned char* key, const unsigned char* iv, size_t padding_size = (size_t)-1);
	static void s_destroy(IMCrypto* obj);

	static bool s_encrypt(char* obuf, size_t& olen, const char* buf, size_t blen, CRYPTO_TYPE ct, PADDING_TYPE pt, const unsigned char* key, const unsigned char* iv, size_t padding_size = (size_t)-1);
	static bool s_encrypt(std::string& out, const char* buf, size_t blen, CRYPTO_TYPE ct, PADDING_TYPE pt, const unsigned char* key, const unsigned char* iv, size_t padding_size = (size_t)-1);
	static bool s_decrypt(char* obuf, size_t& olen, const char* buf, size_t blen, CRYPTO_TYPE ct, PADDING_TYPE pt, const unsigned char* key, const unsigned char* iv, size_t padding_size = (size_t)-1);
	static bool s_decrypt(std::string& out, const char* buf, size_t blen, CRYPTO_TYPE ct, PADDING_TYPE pt, const unsigned char* key, const unsigned char* iv, size_t padding_size = (size_t)-1);

	static bool s_getSize(size_t* keysize, size_t* ivsize, size_t* blocksize, CRYPTO_TYPE ct, PADDING_TYPE pt);

protected:
	explicit IMCrypto();
	virtual ~IMCrypto();
	IMCrypto& operator = (const IMCrypto&) { return *this; }

public:
	size_t getKeySize(void) const;
	size_t getIVSize(void) const;
	size_t getBlockSize(void) const;

	bool encrypt(std::string& out, const char* buf, size_t blen) const;
	bool encrypt(char* out, size_t& olen, const char* buf, size_t blen) const;
	bool decrypt(std::string& out, const char* buf, size_t blen) const;
	bool decrypt(char* out, size_t& olen, const char* buf, size_t blen) const;

protected:
	void*			m_ctx;
};

#endif//!__IMCRYPTO_H__

